From e2f6d4db431e7cb2e21e18bf36783d361697385c Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 12 Jan 2015 03:58:21 +0100 Subject: [PATCH] cssnode: Split into 3 objects - GtkCssWidgetNode for style contexts owned by a widget - GtkCssPathNode for style contexts using a GtkWidgetPath - GtkCssTransientNode for nodes created with gtk_style_context_save()/restore() --- gtk/Makefile.am | 8 +- gtk/gtkcssnode.c | 46 ++++--- gtk/gtkcssnodeprivate.h | 9 +- gtk/gtkcsspathnode.c | 89 ++++++++++++++ gtk/gtkcsspathnodeprivate.h | 58 +++++++++ gtk/gtkcsstransientnode.c | 82 +++++++++++++ gtk/gtkcsstransientnodeprivate.h | 51 ++++++++ gtk/gtkcsswidgetnode.c | 93 ++++++++++++++ gtk/gtkcsswidgetnodeprivate.h | 58 +++++++++ gtk/gtkstylecontext.c | 204 +++++++++++++++++++------------ 10 files changed, 597 insertions(+), 101 deletions(-) create mode 100644 gtk/gtkcsspathnode.c create mode 100644 gtk/gtkcsspathnodeprivate.h create mode 100644 gtk/gtkcsstransientnode.c create mode 100644 gtk/gtkcsstransientnodeprivate.h create mode 100644 gtk/gtkcsswidgetnode.c create mode 100644 gtk/gtkcsswidgetnodeprivate.h diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 13e2651c1d..1af8ecb677 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -401,6 +401,7 @@ gtk_private_h_sources = \ gtkcssnodedeclarationprivate.h \ gtkcssnumbervalueprivate.h \ gtkcssparserprivate.h \ + gtkcsspathnodeprivate.h \ gtkcsspositionvalueprivate.h \ gtkcssproviderprivate.h \ gtkcssrepeatvalueprivate.h \ @@ -416,10 +417,12 @@ gtk_private_h_sources = \ gtkcssstyleprivate.h \ gtkcssstylepropertyprivate.h \ gtkcsstransformvalueprivate.h \ + gtkcsstransientnodeprivate.h \ gtkcsstransitionprivate.h \ gtkcsstypedvalueprivate.h \ gtkcssunsetvalueprivate.h \ gtkcssvalueprivate.h \ + gtkcsswidgetnodeprivate.h \ gtkcustompaperunixdialog.h \ gtkdialogprivate.h \ gtkentryprivate.h \ @@ -632,6 +635,7 @@ gtk_base_c_sources = \ gtkcssnodedeclaration.c \ gtkcssnumbervalue.c \ gtkcssparser.c \ + gtkcsspathnode.c \ gtkcsspositionvalue.c \ gtkcssprovider.c \ gtkcssrepeatvalue.c \ @@ -649,11 +653,13 @@ gtk_base_c_sources = \ gtkcssstyleproperty.c \ gtkcssstylepropertyimpl.c \ gtkcsstransformvalue.c \ + gtkcsstransientnode.c \ gtkcsstransition.c \ gtkcsstypedvalue.c \ gtkcssunsetvalue.c \ - gtkcssvalue.c \ gtkcsstypes.c \ + gtkcssvalue.c \ + gtkcsswidgetnode.c \ gtkdialog.c \ gtkdrawingarea.c \ gtkeditable.c \ diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c index a4b5a6308a..86c0a07992 100644 --- a/gtk/gtkcssnode.c +++ b/gtk/gtkcssnode.c @@ -33,12 +33,27 @@ gtk_css_node_finalize (GObject *object) G_OBJECT_CLASS (gtk_css_node_parent_class)->finalize (object); } +static GtkWidgetPath * +gtk_css_node_real_create_widget_path (GtkCssNode *cssnode) +{ + return gtk_widget_path_new (); +} + +static const GtkWidgetPath * +gtk_css_node_real_get_widget_path (GtkCssNode *cssnode) +{ + return NULL; +} + static void gtk_css_node_class_init (GtkCssNodeClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gtk_css_node_finalize; + + klass->create_widget_path = gtk_css_node_real_create_widget_path; + klass->get_widget_path = gtk_css_node_real_get_widget_path; } static void @@ -47,24 +62,6 @@ gtk_css_node_init (GtkCssNode *cssnode) cssnode->decl = gtk_css_node_declaration_new (); } -GtkCssNode * -gtk_css_node_new (void) -{ - return g_object_new (GTK_TYPE_CSS_NODE, NULL); -} - -GtkCssNode * -gtk_css_node_copy (GtkCssNode *cssnode) -{ - GtkCssNode *copy; - - copy = gtk_css_node_new (); - gtk_css_node_declaration_unref (copy->decl); - copy->decl = gtk_css_node_declaration_ref (cssnode->decl); - - return copy; -} - void gtk_css_node_set_parent (GtkCssNode *cssnode, GtkCssNode *parent) @@ -220,3 +217,16 @@ gtk_css_node_dup_declaration (GtkCssNode *cssnode) { return gtk_css_node_declaration_ref (cssnode->decl); } + +GtkWidgetPath * +gtk_css_node_create_widget_path (GtkCssNode *cssnode) +{ + return GTK_CSS_NODE_GET_CLASS (cssnode)->create_widget_path (cssnode); +} + +const GtkWidgetPath * +gtk_css_node_get_widget_path (GtkCssNode *cssnode) +{ + return GTK_CSS_NODE_GET_CLASS (cssnode)->get_widget_path (cssnode); +} + diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h index 7d217d9a56..fb8bb4de4e 100644 --- a/gtk/gtkcssnodeprivate.h +++ b/gtk/gtkcssnodeprivate.h @@ -45,13 +45,13 @@ struct _GtkCssNode struct _GtkCssNodeClass { GObjectClass object_class; + + GtkWidgetPath * (* create_widget_path) (GtkCssNode *cssnode); + const GtkWidgetPath * (* get_widget_path) (GtkCssNode *cssnode); }; GType gtk_css_node_get_type (void) G_GNUC_CONST; -GtkCssNode * gtk_css_node_new (void); -GtkCssNode * gtk_css_node_copy (GtkCssNode *cssnode); - void gtk_css_node_set_parent (GtkCssNode *cssnode, GtkCssNode *parent); GtkCssNode * gtk_css_node_get_parent (GtkCssNode *cssnode); @@ -94,6 +94,9 @@ GtkCssStyle * gtk_css_node_get_style (GtkCssNode * void gtk_css_node_set_style (GtkCssNode *cssnode, GtkCssStyle *style); +GtkWidgetPath * gtk_css_node_create_widget_path (GtkCssNode *cssnode); +const GtkWidgetPath * gtk_css_node_get_widget_path (GtkCssNode *cssnode); + G_END_DECLS #endif /* __GTK_CSS_NODE_PRIVATE_H__ */ diff --git a/gtk/gtkcsspathnode.c b/gtk/gtkcsspathnode.c new file mode 100644 index 0000000000..85358b4666 --- /dev/null +++ b/gtk/gtkcsspathnode.c @@ -0,0 +1,89 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2014 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtkcsspathnodeprivate.h" +#include "gtkprivate.h" + +G_DEFINE_TYPE (GtkCssPathNode, gtk_css_path_node, GTK_TYPE_CSS_NODE) + +static GtkWidgetPath * +gtk_css_path_node_real_create_widget_path (GtkCssNode *node) +{ + GtkCssPathNode *path_node = GTK_CSS_PATH_NODE (node); + + if (path_node->path == NULL) + return gtk_widget_path_new (); + + return gtk_widget_path_copy (path_node->path); +} + +static const GtkWidgetPath * +gtk_css_path_node_real_get_widget_path (GtkCssNode *node) +{ + GtkCssPathNode *path_node = GTK_CSS_PATH_NODE (node); + + return path_node->path; +} + +static void +gtk_css_path_node_class_init (GtkCssPathNodeClass *klass) +{ + GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass); + + node_class->create_widget_path = gtk_css_path_node_real_create_widget_path; + node_class->get_widget_path = gtk_css_path_node_real_get_widget_path; +} + +static void +gtk_css_path_node_init (GtkCssPathNode *cssnode) +{ +} + +GtkCssNode * +gtk_css_path_node_new (void) +{ + return g_object_new (GTK_TYPE_CSS_PATH_NODE, NULL); +} + +void +gtk_css_path_node_set_widget_path (GtkCssPathNode *node, + GtkWidgetPath *path) +{ + gtk_internal_return_if_fail (GTK_IS_CSS_PATH_NODE (node)); + + if (node->path == path) + return; + + if (node->path) + gtk_widget_path_unref (node->path); + + if (path) + gtk_widget_path_ref (path); + + node->path = path; +} + +GtkWidgetPath * +gtk_css_path_node_get_widget_path (GtkCssPathNode *node) +{ + gtk_internal_return_val_if_fail (GTK_IS_CSS_PATH_NODE (node), NULL); + + return node->path; +} + diff --git a/gtk/gtkcsspathnodeprivate.h b/gtk/gtkcsspathnodeprivate.h new file mode 100644 index 0000000000..0ff89e701a --- /dev/null +++ b/gtk/gtkcsspathnodeprivate.h @@ -0,0 +1,58 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2014 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_CSS_PATH_NODE_PRIVATE_H__ +#define __GTK_CSS_PATH_NODE_PRIVATE_H__ + +#include "gtkcssnodeprivate.h" +#include "gtkwidgetpath.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_CSS_PATH_NODE (gtk_css_path_node_get_type ()) +#define GTK_CSS_PATH_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_PATH_NODE, GtkCssPathNode)) +#define GTK_CSS_PATH_NODE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_PATH_NODE, GtkCssPathNodeClass)) +#define GTK_IS_CSS_PATH_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_PATH_NODE)) +#define GTK_IS_CSS_PATH_NODE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_PATH_NODE)) +#define GTK_CSS_PATH_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_PATH_NODE, GtkCssPathNodeClass)) + +typedef struct _GtkCssPathNode GtkCssPathNode; +typedef struct _GtkCssPathNodeClass GtkCssPathNodeClass; + +struct _GtkCssPathNode +{ + GtkCssNode node; + + GtkWidgetPath *path; +}; + +struct _GtkCssPathNodeClass +{ + GtkCssNodeClass node_class; +}; + +GType gtk_css_path_node_get_type (void) G_GNUC_CONST; + +GtkCssNode * gtk_css_path_node_new (void); + +void gtk_css_path_node_set_widget_path (GtkCssPathNode *node, + GtkWidgetPath *path); +GtkWidgetPath * gtk_css_path_node_get_widget_path (GtkCssPathNode *node); + +G_END_DECLS + +#endif /* __GTK_CSS_PATH_NODE_PRIVATE_H__ */ diff --git a/gtk/gtkcsstransientnode.c b/gtk/gtkcsstransientnode.c new file mode 100644 index 0000000000..723c97a426 --- /dev/null +++ b/gtk/gtkcsstransientnode.c @@ -0,0 +1,82 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2014 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtkcsstransientnodeprivate.h" +#include "gtkprivate.h" + +G_DEFINE_TYPE (GtkCssTransientNode, gtk_css_transient_node, GTK_TYPE_CSS_NODE) + +static GtkWidgetPath * +gtk_css_transient_node_create_widget_path (GtkCssNode *node) +{ + GtkWidgetPath *result; + GtkCssNode *parent; + + parent = gtk_css_node_get_parent (node); + if (parent == NULL) + result = gtk_widget_path_new (); + else + result = gtk_css_node_create_widget_path (parent); + + gtk_widget_path_append_type (result, gtk_css_node_get_widget_type (node)); + gtk_css_node_declaration_add_to_widget_path (gtk_css_node_get_declaration (node), result, -1); + + return result; +} + +static const GtkWidgetPath * +gtk_css_transient_node_get_widget_path (GtkCssNode *node) +{ + GtkCssNode *parent; + + parent = gtk_css_node_get_parent (node); + if (parent == NULL) + return NULL; + + return gtk_css_node_get_widget_path (parent); +} + +static void +gtk_css_transient_node_class_init (GtkCssTransientNodeClass *klass) +{ + GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass); + + node_class->create_widget_path = gtk_css_transient_node_create_widget_path; + node_class->get_widget_path = gtk_css_transient_node_get_widget_path; +} + +static void +gtk_css_transient_node_init (GtkCssTransientNode *cssnode) +{ +} + +GtkCssNode * +gtk_css_transient_node_new (GtkCssNode *parent) +{ + GtkCssNode *result; + + gtk_internal_return_val_if_fail (GTK_IS_CSS_NODE (parent), NULL); + + result = g_object_new (GTK_TYPE_CSS_TRANSIENT_NODE, NULL); + gtk_css_node_declaration_unref (result->decl); + result->decl = gtk_css_node_declaration_ref (parent->decl); + + return result; +} + diff --git a/gtk/gtkcsstransientnodeprivate.h b/gtk/gtkcsstransientnodeprivate.h new file mode 100644 index 0000000000..2fb438a298 --- /dev/null +++ b/gtk/gtkcsstransientnodeprivate.h @@ -0,0 +1,51 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2014 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_CSS_TRANSIENT_NODE_PRIVATE_H__ +#define __GTK_CSS_TRANSIENT_NODE_PRIVATE_H__ + +#include "gtkcssnodeprivate.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_CSS_TRANSIENT_NODE (gtk_css_transient_node_get_type ()) +#define GTK_CSS_TRANSIENT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_TRANSIENT_NODE, GtkCssTransientNode)) +#define GTK_CSS_TRANSIENT_NODE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_TRANSIENT_NODE, GtkCssTransientNodeClass)) +#define GTK_IS_CSS_TRANSIENT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_TRANSIENT_NODE)) +#define GTK_IS_CSS_TRANSIENT_NODE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_TRANSIENT_NODE)) +#define GTK_CSS_TRANSIENT_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_TRANSIENT_NODE, GtkCssTransientNodeClass)) + +typedef struct _GtkCssTransientNode GtkCssTransientNode; +typedef struct _GtkCssTransientNodeClass GtkCssTransientNodeClass; + +struct _GtkCssTransientNode +{ + GtkCssNode node; +}; + +struct _GtkCssTransientNodeClass +{ + GtkCssNodeClass node_class; +}; + +GType gtk_css_transient_node_get_type (void) G_GNUC_CONST; + +GtkCssNode * gtk_css_transient_node_new (GtkCssNode *parent); + +G_END_DECLS + +#endif /* __GTK_CSS_TRANSIENT_NODE_PRIVATE_H__ */ diff --git a/gtk/gtkcsswidgetnode.c b/gtk/gtkcsswidgetnode.c new file mode 100644 index 0000000000..b7932ce5c3 --- /dev/null +++ b/gtk/gtkcsswidgetnode.c @@ -0,0 +1,93 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2014 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtkcsswidgetnodeprivate.h" +#include "gtkprivate.h" +#include "gtkwidgetprivate.h" + +G_DEFINE_TYPE (GtkCssWidgetNode, gtk_css_widget_node, GTK_TYPE_CSS_NODE) + +static GtkWidgetPath * +gtk_css_widget_node_create_widget_path (GtkCssNode *node) +{ + GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node); + + if (widget_node->widget == NULL) + return gtk_widget_path_new (); + + return _gtk_widget_create_path (widget_node->widget); +} + +static const GtkWidgetPath * +gtk_css_widget_node_get_widget_path (GtkCssNode *node) +{ + GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node); + + if (widget_node->widget == NULL) + return NULL; + + return gtk_widget_get_path (widget_node->widget); +} + +static void +gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass) +{ + GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass); + + node_class->create_widget_path = gtk_css_widget_node_create_widget_path; + node_class->get_widget_path = gtk_css_widget_node_get_widget_path; +} + +static void +gtk_css_widget_node_init (GtkCssWidgetNode *cssnode) +{ +} + +GtkCssNode * +gtk_css_widget_node_new (GtkWidget *widget) +{ + GtkCssWidgetNode *result; + + gtk_internal_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + result = g_object_new (GTK_TYPE_CSS_WIDGET_NODE, NULL); + result->widget = widget; + + return GTK_CSS_NODE (result); +} + +void +gtk_css_widget_node_widget_destroyed (GtkCssWidgetNode *node) +{ + gtk_internal_return_if_fail (GTK_IS_CSS_WIDGET_NODE (node)); + gtk_internal_return_if_fail (node->widget != NULL); + + node->widget = NULL; + /* Contents of this node are now undefined. + * So we don't clear the style or anything. + */ +} + +GtkWidget * +gtk_css_widget_node_get_widget (GtkCssWidgetNode *node) +{ + gtk_internal_return_val_if_fail (GTK_IS_CSS_WIDGET_NODE (node), NULL); + + return node->widget; +} diff --git a/gtk/gtkcsswidgetnodeprivate.h b/gtk/gtkcsswidgetnodeprivate.h new file mode 100644 index 0000000000..78c4337fd3 --- /dev/null +++ b/gtk/gtkcsswidgetnodeprivate.h @@ -0,0 +1,58 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2014 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_CSS_WIDGET_NODE_PRIVATE_H__ +#define __GTK_CSS_WIDGET_NODE_PRIVATE_H__ + +#include "gtkcssnodeprivate.h" +#include "gtkwidget.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_CSS_WIDGET_NODE (gtk_css_widget_node_get_type ()) +#define GTK_CSS_WIDGET_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_WIDGET_NODE, GtkCssWidgetNode)) +#define GTK_CSS_WIDGET_NODE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_WIDGET_NODE, GtkCssWidgetNodeClass)) +#define GTK_IS_CSS_WIDGET_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_WIDGET_NODE)) +#define GTK_IS_CSS_WIDGET_NODE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_WIDGET_NODE)) +#define GTK_CSS_WIDGET_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_WIDGET_NODE, GtkCssWidgetNodeClass)) + +typedef struct _GtkCssWidgetNode GtkCssWidgetNode; +typedef struct _GtkCssWidgetNodeClass GtkCssWidgetNodeClass; + +struct _GtkCssWidgetNode +{ + GtkCssNode node; + + GtkWidget *widget; +}; + +struct _GtkCssWidgetNodeClass +{ + GtkCssNodeClass node_class; +}; + +GType gtk_css_widget_node_get_type (void) G_GNUC_CONST; + +GtkCssNode * gtk_css_widget_node_new (GtkWidget *widget); + +void gtk_css_widget_node_widget_destroyed (GtkCssWidgetNode *node); + +GtkWidget * gtk_css_widget_node_get_widget (GtkCssWidgetNode *node); + +G_END_DECLS + +#endif /* __GTK_CSS_WIDGET_NODE_PRIVATE_H__ */ diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c index ef6dcaac0a..2dfe321232 100644 --- a/gtk/gtkstylecontext.c +++ b/gtk/gtkstylecontext.c @@ -33,15 +33,17 @@ #include "gtkcssnodedeclarationprivate.h" #include "gtkcssnodeprivate.h" #include "gtkcssnumbervalueprivate.h" +#include "gtkcsspathnodeprivate.h" #include "gtkcssrgbavalueprivate.h" #include "gtkcssshadowsvalueprivate.h" #include "gtkcssstaticstyleprivate.h" #include "gtkcssstylepropertyprivate.h" #include "gtkcsstransformvalueprivate.h" +#include "gtkcsstransientnodeprivate.h" +#include "gtkcsswidgetnodeprivate.h" #include "gtkdebug.h" #include "gtktypebuiltins.h" #include "gtkintl.h" -#include "gtkwidget.h" #include "gtkwindow.h" #include "gtkprivate.h" #include "gtkwidgetpath.h" @@ -152,8 +154,6 @@ struct _GtkStyleContextPrivate GtkStyleCascade *cascade; GtkStyleContext *parent; GSList *children; - GtkWidget *widget; - GtkWidgetPath *widget_path; GHashTable *style_values; GtkCssNode *cssnode; GSList *saved_nodes; @@ -206,8 +206,8 @@ gtk_style_context_real_changed (GtkStyleContext *context) { GtkStyleContextPrivate *priv = context->priv; - if (priv->widget) - _gtk_widget_style_context_invalidated (priv->widget); + if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode)) + _gtk_widget_style_context_invalidated (gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (priv->cssnode))); } static void @@ -377,7 +377,7 @@ gtk_style_context_init (GtkStyleContext *style_context) priv->screen = gdk_screen_get_default (); /* Create default info store */ - priv->cssnode = gtk_css_node_new (); + priv->cssnode = gtk_css_path_node_new (); gtk_css_node_set_state (priv->cssnode, GTK_STATE_FLAG_DIR_LTR); priv->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue)); @@ -460,15 +460,20 @@ static gboolean gtk_style_context_should_animate (GtkStyleContext *context) { GtkStyleContextPrivate *priv; + GtkWidget *widget; GtkCssStyle *values; gboolean animate; priv = context->priv; - if (priv->widget == NULL) + if (!GTK_IS_CSS_WIDGET_NODE (priv->cssnode)) return FALSE; - if (!gtk_widget_get_mapped (priv->widget)) + widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (priv->cssnode)); + if (widget == NULL) + return FALSE; + + if (!gtk_widget_get_mapped (widget)) return FALSE; values = gtk_style_context_lookup_style (context); @@ -476,7 +481,7 @@ gtk_style_context_should_animate (GtkStyleContext *context) gtk_css_animated_style_is_static (GTK_CSS_ANIMATED_STYLE (values))) return FALSE; - g_object_get (gtk_widget_get_settings (context->priv->widget), + g_object_get (gtk_widget_get_settings (widget), "gtk-enable-animations", &animate, NULL); @@ -522,9 +527,6 @@ gtk_style_context_finalize (GObject *object) gtk_style_context_set_cascade (style_context, NULL); - if (priv->widget_path) - gtk_widget_path_free (priv->widget_path); - g_hash_table_destroy (priv->style_values); while (priv->saved_nodes) @@ -636,16 +638,16 @@ create_query_path (GtkStyleContext *context, const GtkCssNodeDeclaration *decl, gboolean is_root) { - GtkStyleContextPrivate *priv; + GtkCssNode *root; GtkWidgetPath *path; guint length; - priv = context->priv; - path = priv->widget ? _gtk_widget_create_path (priv->widget) : gtk_widget_path_copy (priv->widget_path); + root = gtk_style_context_get_root (context); + + path = gtk_css_node_create_widget_path (root); length = gtk_widget_path_length (path); if (!is_root) { - GtkCssNode *root = gtk_style_context_get_root (context); if (length > 0) gtk_css_node_declaration_add_to_widget_path (gtk_css_node_get_declaration (root), path, length - 1); @@ -911,9 +913,12 @@ gtk_style_context_set_invalid (GtkStyleContext *context, if (invalid) { + GtkWidget *widget; + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; - if (GTK_IS_RESIZE_CONTAINER (priv->widget)) - _gtk_container_queue_restyle (GTK_CONTAINER (priv->widget)); + if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode) && + GTK_IS_RESIZE_CONTAINER (widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (priv->cssnode)))) + _gtk_container_queue_restyle (GTK_CONTAINER (widget)); else if (priv->parent) gtk_style_context_set_invalid (priv->parent, TRUE); G_GNUC_END_IGNORE_DEPRECATIONS; @@ -962,15 +967,31 @@ void _gtk_style_context_set_widget (GtkStyleContext *context, GtkWidget *widget) { + GtkStyleContextPrivate *priv; + g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget)); + g_return_if_fail (!gtk_style_context_is_saved (context)); - context->priv->widget = widget; + priv = context->priv; + + if (!GTK_IS_CSS_WIDGET_NODE (priv->cssnode)) + { + g_object_unref (priv->cssnode); + priv->cssnode = gtk_css_widget_node_new (widget); + gtk_css_node_set_state (priv->cssnode, GTK_STATE_FLAG_DIR_LTR); + gtk_css_node_set_style (priv->cssnode, gtk_css_static_style_get_default (priv->screen)); + } if (widget) - gtk_css_node_set_widget_type (context->priv->cssnode, G_OBJECT_TYPE (widget)); + { + gtk_css_node_set_widget_type (priv->cssnode, G_OBJECT_TYPE (widget)); + } else - gtk_css_node_set_widget_type (context->priv->cssnode, G_TYPE_NONE); + { + gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_NONE); + gtk_css_widget_node_widget_destroyed (GTK_CSS_WIDGET_NODE (priv->cssnode)); + } _gtk_style_context_update_animating (context); @@ -1214,7 +1235,6 @@ gtk_style_context_get_property (GtkStyleContext *context, GtkStateFlags state, GValue *value) { - GtkStyleContextPrivate *priv; GtkCssStyle *values; GtkStyleProperty *prop; @@ -1222,9 +1242,6 @@ gtk_style_context_get_property (GtkStyleContext *context, g_return_if_fail (property != NULL); g_return_if_fail (value != NULL); - priv = context->priv; - g_return_if_fail (priv->widget != NULL || priv->widget_path != NULL); - prop = _gtk_style_property_lookup (property); if (prop == NULL) { @@ -1499,30 +1516,29 @@ void gtk_style_context_set_path (GtkStyleContext *context, GtkWidgetPath *path) { - GtkStyleContextPrivate *priv; + GtkCssNode *root; g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); g_return_if_fail (path != NULL); - priv = context->priv; - g_return_if_fail (priv->widget == NULL); + root = gtk_style_context_get_root (context); + g_return_if_fail (GTK_IS_CSS_PATH_NODE (root)); - if (priv->widget_path) + if (path) { - gtk_widget_path_free (priv->widget_path); - priv->widget_path = NULL; - gtk_css_node_set_widget_type (context->priv->cssnode, G_TYPE_NONE); + GtkWidgetPath *copy = gtk_widget_path_copy (path); + gtk_css_path_node_set_widget_path (GTK_CSS_PATH_NODE (root), copy); + if (gtk_widget_path_length (copy)) + gtk_css_node_set_widget_type (root, + gtk_widget_path_iter_get_object_type (copy, -1)); + gtk_widget_path_unref (copy); } - - if (path) + else { - priv->widget_path = gtk_widget_path_copy (path); - if (gtk_widget_path_length (path)) - gtk_css_node_set_widget_type (context->priv->cssnode, - gtk_widget_path_iter_get_object_type (path, -1)); + gtk_css_path_node_set_widget_path (GTK_CSS_PATH_NODE (root), NULL); + gtk_css_node_set_widget_type (root, G_TYPE_NONE); } - _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY); } @@ -1539,13 +1555,7 @@ gtk_style_context_set_path (GtkStyleContext *context, const GtkWidgetPath * gtk_style_context_get_path (GtkStyleContext *context) { - GtkStyleContextPrivate *priv; - - priv = context->priv; - if (priv->widget) - return gtk_widget_get_path (priv->widget); - else - return priv->widget_path; + return gtk_css_node_get_widget_path (gtk_style_context_get_root (context)); } /** @@ -1641,7 +1651,7 @@ gtk_style_context_save (GtkStyleContext *context) if (!gtk_style_context_is_saved (context)) gtk_style_context_lookup_style (context); - cssnode = gtk_css_node_copy (priv->cssnode); + cssnode = gtk_css_transient_node_new (priv->cssnode); gtk_css_node_set_parent (cssnode, gtk_style_context_get_root (context)); priv->saved_nodes = g_slist_prepend (priv->saved_nodes, priv->cssnode); @@ -2021,6 +2031,7 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context, GParamSpec *pspec) { GtkStyleContextPrivate *priv; + GtkWidgetPath *path; PropertyValue *pcache, key = { 0 }; guint i; @@ -2048,13 +2059,12 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context, g_param_spec_ref (pcache->pspec); g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec)); - if (priv->widget || priv->widget_path) + path = gtk_css_node_create_widget_path (gtk_style_context_get_root (context)); + if (path && gtk_widget_path_length (path) > 0) { - GtkWidgetPath *widget_path = priv->widget ? _gtk_widget_create_path (priv->widget) : priv->widget_path; - if (gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade), - widget_path, - gtk_widget_path_iter_get_state (widget_path, -1), + path, + gtk_widget_path_iter_get_state (path, -1), pspec, &pcache->value)) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS; @@ -2097,16 +2107,14 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context, G_GNUC_END_IGNORE_DEPRECATIONS; - if (priv->widget) - gtk_widget_path_free (widget_path); + gtk_widget_path_unref (path); return &pcache->value; } - - if (priv->widget) - gtk_widget_path_free (widget_path); } + gtk_widget_path_unref (path); + /* not supplied by any provider, revert to default */ g_param_value_set_default (pspec, &pcache->value); @@ -2129,7 +2137,7 @@ gtk_style_context_get_style_property (GtkStyleContext *context, const gchar *property_name, GValue *value) { - GtkStyleContextPrivate *priv; + GtkCssNode *root; GtkWidgetClass *widget_class; GParamSpec *pspec; const GValue *peek_value; @@ -2139,18 +2147,27 @@ gtk_style_context_get_style_property (GtkStyleContext *context, g_return_if_fail (property_name != NULL); g_return_if_fail (value != NULL); - priv = context->priv; + root = gtk_style_context_get_root (context); - if (priv->widget) + if (GTK_IS_CSS_WIDGET_NODE (root)) { - widget_type = G_OBJECT_TYPE (priv->widget); + GtkWidget *widget; + + widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (root)); + if (widget == NULL) + return; + + widget_type = G_OBJECT_TYPE (widget); } - else + else if (GTK_IS_CSS_PATH_NODE (root)) { - if (!priv->widget_path) + GtkWidgetPath *path; + + path = gtk_css_path_node_get_widget_path (GTK_CSS_PATH_NODE (root)); + if (path == NULL) return; - widget_type = gtk_widget_path_get_object_type (priv->widget_path); + widget_type = gtk_widget_path_get_object_type (path); if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET)) { @@ -2160,6 +2177,10 @@ gtk_style_context_get_style_property (GtkStyleContext *context, return; } } + else + { + return; + } widget_class = g_type_class_ref (widget_type); pspec = gtk_widget_class_find_style_property (widget_class, property_name); @@ -2201,25 +2222,34 @@ void gtk_style_context_get_style_valist (GtkStyleContext *context, va_list args) { - GtkStyleContextPrivate *priv; + GtkCssNode *root; const gchar *prop_name; GType widget_type; g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); prop_name = va_arg (args, const gchar *); - priv = context->priv; + root = gtk_style_context_get_root (context); - if (priv->widget) + if (GTK_IS_CSS_WIDGET_NODE (root)) { - widget_type = G_OBJECT_TYPE (priv->widget); + GtkWidget *widget; + + widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (root)); + if (widget == NULL) + return; + + widget_type = G_OBJECT_TYPE (widget); } - else + else if (GTK_IS_CSS_PATH_NODE (root)) { - if (!priv->widget_path) + GtkWidgetPath *path; + + path = gtk_css_path_node_get_widget_path (GTK_CSS_PATH_NODE (root)); + if (path == NULL) return; - widget_type = gtk_widget_path_get_object_type (priv->widget_path); + widget_type = gtk_widget_path_get_object_type (path); if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET)) { @@ -2229,6 +2259,10 @@ gtk_style_context_get_style_valist (GtkStyleContext *context, return; } } + else + { + return; + } while (prop_name) { @@ -2894,20 +2928,25 @@ gtk_style_context_should_create_transitions (GtkStyleContext *context, GtkCssStyle *previous_style) { GtkStyleContextPrivate *priv; + GtkWidget *widget; gboolean animate; priv = context->priv; - if (priv->widget == NULL) + if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode)) return FALSE; - if (!gtk_widget_get_mapped (priv->widget)) + widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (priv->cssnode)); + if (widget == NULL) + return FALSE; + + if (!gtk_widget_get_mapped (widget)) return FALSE; if (previous_style == gtk_css_static_style_get_default ()) return FALSE; - g_object_get (gtk_widget_get_settings (context->priv->widget), + g_object_get (gtk_widget_get_settings (widget), "gtk-enable-animations", &animate, NULL); @@ -2952,10 +2991,17 @@ _gtk_style_context_validate (GtkStyleContext *context, if (G_UNLIKELY (gtk_style_context_is_saved (context))) { - g_warning ("unmatched gtk_style_context_save/restore() detected while validating context for %s %p", - priv->widget ? gtk_widget_get_name (priv->widget) : "widget path", - priv->widget ? (gpointer) priv->widget : (gpointer) priv->widget_path); cssnode = gtk_style_context_get_root (context); + if (GTK_IS_CSS_WIDGET_NODE (cssnode)) + { + GtkWidget *widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (cssnode)); + g_warning ("unmatched gtk_style_context_save/restore() detected while validating context for %s %p", + gtk_widget_get_name (widget), widget); + } + else + { + g_warning ("unmatched gtk_style_context_save/restore() detected while validating context"); + } } else cssnode = priv->cssnode; @@ -3065,12 +3111,12 @@ _gtk_style_context_queue_invalidate (GtkStyleContext *context, priv = context->priv; - if (priv->widget != NULL) + if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode)) { priv->pending_changes |= change; gtk_style_context_set_invalid (context, TRUE); } - else if (priv->widget_path != NULL) + else if (GTK_IS_CSS_PATH_NODE (priv->cssnode)) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS; gtk_style_context_invalidate (context); -- 2.30.2